package boofbridgeimaj.image.feature.util;

import boofbridgeimaj.image.util.ImajToBoof;
import boofcv.abst.feature.describe.ConvertTupleDesc;
import boofcv.abst.feature.detdesc.DetectDescribePoint;
import boofcv.struct.feature.SurfFeature;
import boofcv.struct.feature.TupleDesc;
import boofcv.struct.feature.TupleDesc_S8;
import boofcv.struct.image.ImageFloat32;
import georegression.struct.point.Point2D_F64;
import org.openimaj.feature.local.list.LocalFeatureList;
import org.openimaj.feature.local.list.MemoryLocalFeatureList;
import org.openimaj.image.FImage;
import org.openimaj.image.feature.local.engine.Engine;
import org.openimaj.image.feature.local.keypoints.Keypoint;
import org.openimaj.image.feature.local.keypoints.KeypointLocation;

/**
 * Wrapper class which allows {@link DetectDescribePoint} in BoofCV to be used as a {@link Engine} in OpenIMAJ.
 *
 * @author Peter Abeles
 */
public class DetectDescribePointToEngine_F32<TD extends TupleDesc> implements Engine<Keypoint, FImage> {

	// feature detector
	DetectDescribePoint<ImageFloat32, TD> alg;
	// Converts the original description into the Keypoint format
	ConvertTupleDesc<TD,TupleDesc_S8> converter;
	// Storage for image in BoofCV format
	ImageFloat32 bimage;

	// storage for the descriptor in its original format
	TD workDesc;
	// wrapper used to convert directly into the Keypoint description
	TupleDesc_S8 outHack = new TupleDesc_S8(1);

	public DetectDescribePointToEngine_F32(DetectDescribePoint<ImageFloat32, TD> alg,
										   ConvertTupleDesc<TD, TupleDesc_S8> converter) {
		this.alg = alg;
		this.converter = converter;
		workDesc = alg.createDescription();
	}

	@Override
	public LocalFeatureList<Keypoint> findFeatures(FImage fImage) {
		bimage = ImajToBoof.convert(fImage, bimage);

		long before = System.currentTimeMillis();
		alg.detect(bimage);
		long after = System.currentTimeMillis();

		System.out.println("delta "+(after-before));

		MemoryLocalFeatureList<Keypoint> ret = new MemoryLocalFeatureList<Keypoint>();

		for( int i = 0; i < alg.getNumberOfFeatures(); i++ ) {
			TD desc = alg.getDescriptor(i);
			Point2D_F64 p = alg.getLocation(i);
			float scale = (float) alg.getScale(i);
			float ori = (float) alg.getOrientation(i);

			Keypoint kp = new Keypoint(desc.size());
			kp.setLocation(new KeypointLocation((float)p.x,(float)p.y,ori,scale));

			// Convert and copy the description over to Keypoint
			// just reference the array instead of creating a new instance
			outHack.value = kp.ivec;
			converter.convert(desc,outHack);

			ret.add(kp);
		}

		return ret;
	}

}
